package com.ocp.socket.server.mina;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.session.IoSession;

import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Auther: zhangzh
 * @Date: 2019/1/23 21:49
 * @Description:
 * @Version: 1.0.0
 */
public class SocketManager {

    private Log log = LogFactory.getLog(SocketManager.class);

    // 密钥
    public static final byte[] KEY = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
    //偏移量
    public static final byte[] KEYIV = { 1, 2, 3, 4, 5, 6, 7, 8 };

    public static final String USER_HOST = "host";

    public static final String USER_LOGIN_TIME = "logintime";

    public static final String SESSION_ID = "sessionId";

    //数据头标志
    public static final String MESSAGE_START = "{{";
    //消息包体长度的长度
    public static final int MESSAGE_BODY_LEN= 4;
    //消息包体长度
    public static final int MESSAGE_BODY_LENGTH = 24;
    //终端类型 的开始下标
    public static final int MODEL_INDEX = 0;
    //终端类型长度
    public static final int MODEL_LENGTH = 4;
    //终端识别码 的开始下标
    public static final int SN_INDEX = 4;
    //终端识别码长度
    public static final int SN_LENGTH = 16;
    //数据日期下标
    public static final int DATA_TIME_INDEX = 24;
    //数据日期长度
    public static final int DATA_TIME_LENGTH = 14;
    //数据开始下标
    public static final int DATA_INDEX = 38;
    //数据分隔符
    public static final String DATA_SEPARATOR = ",";
    //线路标识长度
    public static final int DATA_LINE_LENGTH = 3;
    //数据值长度
    public static final int DATA_VAL_LENGTH = 5;
    //数据值单位长度
    public static final int DATA_VAL_UNIT_LENGTH = 3;
    //数据挤奶路线下标
    public static final int DATA_MILK_LINE_INDEX = 38;
    //数据挤奶路线下标
    public static final int DATA_MILK_LINE_LENGTH = 3;
    //数据挤奶信号下标
    public static final int DATA_MILK_LINE_VAL_INDEX = 41;
    //数据挤奶信号下标
    public static final int DATA_MILK_LINE_VAL_LENGTH = 2;
    //数据清洗路线下标
    public static final int DATA_CLEAN_LINE_INDEX = 43;
    //数据清洗路线下标
    public static final int DATA_CLEAN_LINE_LENGTH = 3;
    //数据清洗信号下标
    public static final int DATA_CLEAN_LINE_VAL_INDEX = 46;
    //数据清洗信号下标
    public static final int DATA_CLEAN_LINE_VAL_LENGTH = 2;



    //结束标志
    public static final String MESSAGE_END = "}}";

    private static final SocketManager manager = new SocketManager();

    private final Map<Long, IoSession> online = new HashMap<Long, IoSession>();

    private SocketManager() {
    }

    public static SocketManager getInstance() {
        return manager;
    }

    public Map<Long, IoSession> getOnline() {
        return online;
    }

    /**
     *
     * @function:添加用户信息到在线用户列表
     * @param userId
     * @param session
     * @param moduleName
     * @author: mengqingyu    2013-7-30 下午03:38:47

    public void addUserToOnlineMap(String userId, IoSession session, String moduleName) {
        InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress();
        session.setAttribute(SESSION_ID, session.getId());
        session.setAttribute(USER_HOST, remoteAddress.getAddress().getHostAddress());
        session.setAttribute(USER_LOGIN_TIME, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        session.setAttribute("userId", userId);
        this.online.put(userId, session);
    }
     */

    /**
     * 添加用户信息到在线用户列表
     * @param sessionId
     * @param session
     */
    public void addSessionToOnlineMap(Long sessionId,IoSession session){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String newDate = sdf.format(new Date());
        InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress();
        String hostAddress = remoteAddress.getAddress().getHostAddress();
        log.info("当前时间：["+newDate +"]");
        log.info("创建新的连接ID：["+sessionId+"];IP地址："+hostAddress+"]");
        session.setAttribute(USER_HOST, hostAddress);
        session.setAttribute(USER_LOGIN_TIME, newDate);
        this.online.put(sessionId, session);
    }

    /**
     * session 追加信息
     * @param session
     * @param key
     * @param val
     */
    public void addSessionInfo(IoSession session,String key,String val){
        log.info("SESSION:["+session.getId() +"] 追加存储 key:["+key+"],value:["+val+"]");
        session.setAttribute(key,val);
    }


    /**
     *
     * @function:从在线用户列表删除用户信息
     * @param seesionId
     * @author: mengqingyu    2013-7-30 下午03:38:38
     */
    public void removeSessionToOnlineMap(Long seesionId) {
        this.online.remove(seesionId);
    }

    /**
     *
     * @function:从在线用户列表删除用户信息
     * @param userId
     * @author: mengqingyu    2013-7-30 下午03:38:38
     */
    public void removeUserFromOnlineMap(String userId) {
        IoSession session = (IoSession) this.online.get(userId);
        this.online.remove(userId);
        session.close(true);
    }

    /**
     *
     * @function:根据sessionId删除用户
     * @param sessionId
     * @author: mengqingyu    2013-7-30 下午03:38:10

    public void removeUserBySessionId(long sessionId) {
        for(Map.Entry<Long, IoSession> entry:online.entrySet()){
            String userId = entry.getKey();
            IoSession session = entry.getValue();
            if (sessionId == (Long)session.getAttribute(SESSION_ID)) {
                log.info("Exception from " + sessionId + " <--> " + userId + "<--> is connected:" + session.isConnected());
                this.removeUserFromOnlineMap(userId);
                break;
            }
        }
    }
     */

    /**
     * 获取在线用户列表
     *
     * @function:
     * @return
     * @author: tangtaibin 2010-10-19 下午02:31:06
     */
    public List<Long> getOnlineUsers() {
        Set<Long> keySet = this.online.keySet();
        return new ArrayList<Long>(keySet);
    }

    /**
     * 获取在线用户Seesion列表
     *
     * @function:
     * @return
     * @author: tangtaibin 2010-10-19 下午02:31:06
     */
    public void sendToAllUsers(String msg) {
        for(Map.Entry<Long, IoSession> entry:online.entrySet()){
//            Long userId = entry.getKey();
            IoSession session = entry.getValue();
            try{
                session.write(msg);
            }catch (Exception e){
                log.info("客户端发送失败："+session.getId());
                session.closeNow();
                SocketManager.getInstance().removeSessionToOnlineMap(session.getId());
            }
        }
    }


    /**
     * 获取用户Session
     *
     * @function:
     * @param userid
     * @return
     * @author: liujuan 2011-1-7 上午09:08:16
     */
    public IoSession getUserSession(String userid) {
        return this.online.get(userid);
    }

    /**
     * 给某个App用户发送消息
     *
     * @function:
     * @param userid
     * @param msg
     * @author: tangtaibin 2010-10-19 下午02:31:25
     */
    public synchronized void sendToUser(String userid, String msg) {
        IoSession session = this.online.get(userid);
        log.info("MSG_APP To: " + msg);
        StringBuffer msgBuf = new StringBuffer();
        msgBuf.append(MESSAGE_START);
        try {
            session.write(MESSAGE_START + msg + MESSAGE_END);
            log.info("MSG_APP: " + msg);
        } catch (Exception e) {
            log.error(e);
        }
    }

    public String getMsgAndLen(String msg){
        StringBuffer msgBuf = new StringBuffer();
        int len = msg.length();
        msgBuf.append(String.format("%0"+MESSAGE_BODY_LEN+"d",len));
        msgBuf.append(msg);
        return msgBuf.toString();
    }
}

